package com.chancein.cloud.report.charts.handler;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chancein.cloud.report.charts.common.util.PostTool;
import lombok.extern.slf4j.Slf4j;

import java.net.SocketException;

import static com.chancein.cloud.report.charts.common.constant.CommonConstant.*;
import static com.chancein.cloud.report.charts.common.constant.HttpConstant.*;
import static com.chancein.cloud.report.charts.common.constant.MapConstant.*;
import static com.chancein.cloud.report.charts.common.constant.OcrDataConstant.*;
import static com.chancein.cloud.report.charts.common.util.PostTool.postOcr;

/**
 * Exception 处理
 *
 * @author: LiaoZiHao
 * @date: 2023/8/2 17:40
 * Copyright © 2022 Hundsun Technologies Inc. All Rights Reserved
 */
@Slf4j
@Deprecated
public class ReportChartsExceptionHandler {
    /**
     * 504 网关熔断超时错误
     *
     * @date 2023/8/2 17:46
     * @author liaozihao
     * @param requestBody     OCR请求体
     * @param authentication  权限码
     * @return {@link String}
     */
    public static String httpGateWayTimeOut504(String requestBody, String authentication) {
        String reportChartsId = fetchReportChartsId(requestBody);
        log.error("[OCR]解析接口出现[网关504超时错误]; 错误数据[id=" + reportChartsId + "]");
        String key = HTTP_GATEWAY_TIMEOUT + reportChartsId;
        String gatewayKey = HTTP_GATEWAY_TIMEOUT + Thread.currentThread().getName();
        sameErrorCountMap.compute(key, (k, val) -> val == null ? 1 : val + 1);
        Integer sameErrorCount = sameErrorCountMap.get(key);
        // 对本条超时数据，重复请求三次
        if (sameErrorCount <= SAME_GATEWAY_TIMEOUT_ERROR_COUNT) {
            log.error("[OCR]错误数据[id=" + reportChartsId + "]重新发起请求中...重试 " + sameErrorCount + " 次");
            String ocrData = postOcr(requestBody, authentication);
            if (StrUtil.equals(ocrData.substring(2, 10), OCR_DATA_LIST)) {
                sameErrorCountMap.remove(key);
                globalErrorCountMap.replace(gatewayKey, 0);
                log.info("[OCR]错误数据[id=" + reportChartsId + "]重新获取ocrData成功!");
                return ocrData;
            }
        }
        // 重复请求三次后还是超时，加入全局错误中
        log.error("[Global UnGateWayTimeOut Error Recording]");
        globalErrorCountMap.compute(gatewayKey, (k, val) -> val == null ? 1 : val + 1);
        if (globalErrorCountMap.get(gatewayKey) > GLOBAL_GATEWAY_TIMEOUT_ERROR_COUNT) {
            // 1条线程发起 getExcel 请求超时25次，说明 OCR 识别接口已经崩了。
            // 暂停线程，1小时后重试。
            try {
                log.error("[OCR]错误次数超过25次; 线程暂停60分钟，60分钟后再次发起OCR请求...");
                Thread.sleep(OCR_504_DELAY_TIME);
                globalErrorCountMap.replace(gatewayKey, 0);
                return postOcr(requestBody, authentication);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "id=" + reportChartsId + ", [HTTP_GATEWAY_TIME_OUT 504]; 解析OCR的getExcel接口网关超时熔断终止了OCR的识别";
    }
    /**
     * 401 token 失效错误
     *
     * @date 2023/8/2 17:46
     * @author liaozihao
     * @param requestBody OCR请求体
     * @return {@link String}
     */
    public static String httpUnAuthorized401(String requestBody) {
        String reportChartsId = fetchReportChartsId(requestBody);
        log.error("[OCR]解析接口出现[系统401权限错误]; 错误数据[id=" + reportChartsId + "]");
        String key = HTTP_UNAUTHORIZED + reportChartsId;
        sameErrorCountMap.compute(key, (k, val) -> val == null ? 1 : val + 1);
        Integer sameErrorCount = sameErrorCountMap.get(key);
        // 对本条造成401错误数据，重复请求5次。
        // 有可能是拿到 token 请求还是 401 报错（199:8088 环境经常出这个错误）
        if (sameErrorCount > SAME_UNAUTHORIZED_ERROR_COUNT) {
            try {
                log.error("[OCR]错误次数超过5次; 线程暂停30分钟，30分钟后再次发起auth + OCR请求...");
                Thread.sleep(OCR_401_DELAY_TIME);
                sameErrorCountMap.replace(key, 0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        String auth = PostTool.postAuth(tokenReq);
        if (auth.split(StrUtil.DASHED).length == 5) {
            String threadName = Thread.currentThread().getName();
            log.info(threadName + " 获取新[token=" + auth + "]");
            //tokenMap.replace(threadName, auth);
            return postOcr(requestBody, auth);
        }
        return "id=" + reportChartsId + ", [HTTP_UNAUTHORIZED 401]; 解析OCR的getExcel接口出现无权限的错误终止了OCR的识别";
    }
    /**
     * OCR 500 未知错误
     *
     * @date 2023/8/2 17:46
     * @author liaozihao
     * @param requestBody OCR请求体
     * @return {@link String}
     */
    public static String httpOcrInternalError500(String requestBody) {
        String reportChartsId = fetchReportChartsId(requestBody);
        log.error("[OCR]解析接口出现[系统500未知错误]; 错误数据[id=" + reportChartsId + "]");
        return "id=" + reportChartsId + ", [HTTP_INTERNAL_ERROR 500]; 解析OCR的getExcel接口未知错误终止了OCR的识别";
    }
    /**
     * 登录获取 SubmitLogin 接口 500 未知错误
     *
     * @date 2023/8/2 17:46
     * @author liaozihao
     * @param requestBody OCR请求体
     * @return {@link String}
     */
    public static String httpLoginInternalError500(String requestBody) {
        JSONObject tokenReqJson = JSON.parseObject(requestBody);
        String accountName = tokenReqJson.getString("accountName");
        String key = HTTP_UNAUTHORIZED + accountName;
        sameErrorCountMap.compute(key, (k, val) -> val == null ? 1 : val + 1);
        Integer sameErrorCount = sameErrorCountMap.get(key);
        if (sameErrorCount <= SAME_UNAUTHORIZED_ERROR_COUNT) {
            log.error("[SubmitLogin]登录接口出现[500未知错误];accountName=[" + accountName + "]重新发起请求中...重试[" + sameErrorCount + "]次");
            String auth = PostTool.postAuth(tokenReq);
            if (auth.split(StrUtil.DASHED).length == 5) {
                return auth;
            }
        } else {
            // 同一条研报图表超时 5 次
            // 理论上来说是不可能出现这种情况的，所以 SubmitLogin 接口肯定是崩了。线程暂停十分钟后再次请求
            log.error("[SubmitLogin]错误次数超过5次; 线程暂停10分钟，10分钟后再次发起SubmitLogin请求...");
            try {
                Thread.sleep(LOGIN_500_DELAY_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 暂停10分钟之后，同一错误次数归为默认值
            sameErrorCountMap.replace(key, 0);
            String auth = PostTool.postAuth(tokenReq);
            if (auth.split(StrUtil.DASHED).length == 5) {
                return auth;
            }
        }
        return "[HTTP_INTERNAL_ERROR 500]; 系统的SubmitLogin登录接口出现500未知错误无法获取token";
    }
    /**
     * 登录接口 404 错误
     *
     * @date 2023/8/7 17:54
     * @author liaozihao
     * @param requestBody OCR 请求体
     * @return {@link String}
     */
    public static String httpLoginFileNotFound404(String requestBody) {
        JSONObject tokenReqJson = JSON.parseObject(requestBody);
        String accountName = tokenReqJson.getString("accountName");
        String key = HTTP_NOT_FOUND + accountName;
        sameErrorCountMap.compute(key, (k, val) -> val == null ? 1 : val + 1);
        Integer sameErrorCount = sameErrorCountMap.get(key);
        if (sameErrorCount <= SAME_NOT_FOUND_ERROR_COUNT) {
            log.error("[SubmitLogin]登录接口出现[404接口路径找不到错误];accountName=[" + accountName + "]重新发起请求中...重试[" + sameErrorCount + "]次");
            String auth = PostTool.postAuth(tokenReq);
            if (auth.split(StrUtil.DASHED).length == 5) {
                return auth;
            }
        } else {
            // 同一条研报图表超时 5 次
            // 理论上来说是不可能出现 404 这种情况的，所以 SubmitLogin 接口肯定是崩了。线程暂停30分钟后再次请求。
            log.error("[SubmitLogin]错误次数超过5次; 线程暂停30分钟，30分钟后再次发起SubmitLogin请求...");
            try {
                Thread.sleep(LOGIN_404_DELAY_TIME);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 暂停30分钟之后，同一错误次数归为默认值
            sameErrorCountMap.replace(key, 0);
            String auth = PostTool.postAuth(tokenReq);
            if (auth.split(StrUtil.DASHED).length == 5) {
                return auth;
            }
        }
        return "[HTTP_NOT_FOUND_ERROR 404]; 系统的SubmitLogin登录接口出现404路径错误无法获取token";
    }
    /**
     * SocketException 异常
     *
     * @date 2023/8/2 18:11
     * @author liaozihao
     * @param requestBody OCR请求体
     * @param e 网络异常
     * @return {@link String}
     */
    public static String httpSocketException(String requestBody, SocketException e) {
        String reportChartsId = fetchReportChartsId(requestBody);
        if ("Connection reset".equals(e.getMessage())) {
            log.error("[OCR]解析接口出现[Connection reset错误]; 错误数据[id=" + reportChartsId + "]");
            return "id=" + reportChartsId + ", [Connection reset]; 解析OCR的getExcel接口出现Connection reset终止了OCR的识别";
        } else {
            String exMsg = e.getMessage();
            log.error("[OCR]解析接口出现[" + exMsg + "]错误; 错误数据[id=" + reportChartsId + "]");
            return "id=" + reportChartsId + ", [" + exMsg + "]; 解析OCR的getExcel接口出现" + exMsg + "终止了OCR的识别";
        }
    }
    /**
     * IOException 异常
     *
     * @date 2023/8/2 18:11
     * @author liaozihao
     * @param requestBody OCR请求体
     * @return {@link String}
     */
    public static String httpIOException(String requestBody) {
        String reportChartsId = fetchReportChartsId(requestBody);
        log.error("[OCR]postOcr函数出现 IO 未知错误");
        return "id=" + reportChartsId + ", [IOException]; postOcr函数出现 IO 未知错误";
    }
    /**
     * 根据请求体提取研报图表ID
     *
     * @date 2023/8/7 15:30
     * @author liaozihao
     * @param requestBody 请求体
     * @return {@link String}
     */
    public static String fetchReportChartsId(String requestBody) {
        JSONObject reqJsonObj = JSONObject.parseObject(requestBody);
        JSONObject chartJson = JSONObject.parseObject(reqJsonObj.getString("chartJson"));
        return chartJson.getString("id");
    }
}
